package luj.tool.jnproxyan.proxy.network.ssh.connect;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.Session;
import luj.bean.api.BeanContext;
import luj.bean.api.bean.Bean;
import luj.cluster.api.actor.Tellable;
import luj.tool.jnproxyan.proxy.network.socks.actor.root.message.request.connect.finish2.ConnectFinish2Msg;
import luj.tool.jnproxyan.proxy.network.ssh.tunnel.SshTunnel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class SshForwardConnector {

  public SshForwardConnector(Session ssh, String targetHost, int targetPort, Tellable socksRef, Long reqId, BeanContext lujbean) {
    _ssh = ssh;
    _targetHost = targetHost;
    _targetPort = targetPort;
    _socksRef = socksRef;
    _reqId = reqId;
    _lujbean = lujbean;
  }

  public void connect() throws Exception {
    if (!_ssh.isConnected()) {
      _ssh.connect();
    }

    Channel sshChannel = _ssh.getStreamForwarder(_targetHost, _targetPort);
    PipedOutputStream c2sOut = new PipedOutputStream();
    PipedInputStream s2cIn = new PipedInputStream();

    sshChannel.setInputStream(new PipedInputStream(c2sOut));
    sshChannel.setOutputStream(new PipedOutputStream(s2cIn));

    sshChannel.connect(1000);
    new RemoteDataReceiver(s2cIn, new byte[1024], _socksRef, _reqId, _lujbean).receive();

    Bean<ConnectFinish2Msg> msg = _lujbean.createBean(ConnectFinish2Msg.class);
    msg.setField(m -> m::reqId, _reqId);
    msg.setField(m -> m::connectResult, new SshTunnel(c2sOut));
    _socksRef.tell(msg.getValueInstance());
  }

  private static final Logger LOG = LoggerFactory.getLogger(SshForwardConnector.class);

  private final Session _ssh;

  private final String _targetHost;
  private final int _targetPort;

  private final Tellable _socksRef;
  private final Long _reqId;
  private final BeanContext _lujbean;
}
